iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0

嗨我是k66,今天是系列文Day23,祝大家中秋節快樂!本篇延續前篇實作按B進入Boot Menu。前篇完成「按B」及「進入Boot Menu」,本篇要實作「選擇Kernel」功能。在進入程式碼前,先科普個小知識,Kernel可想像成OS的核心程式碼。常用的GRUB是Bootloader,它會讓使用者選擇要進入哪個作業系統(或哪個Kernel),因此,本篇BootMenu會設計成讓使用者輸入1或2進入Kernel1或Kernel2。

放碼上來!程式碼連結


  • BootMenu()
static void BootMenu()
{
    // 設定字為red(0x04),並且清除畫面
    gST -> ConOut -> SetAttribute(gST->ConOut,0x4);
    gST -> ConOut -> ClearScreen(gST->ConOut);
    Print(L"*******************************\n");
    Print(L"|          Boot Menu          |\n");
    Print(L"|-----------------------------|\n");
    Print(L"|                             |\n");
    Print(L"|                             |\n");
    Print(L"|                             |\n");
    Print(L"|                             |\n");
    Print(L"*******************************\n");
    
    while(1)
    {
        Status = gST->ConIn->ReadKeyStroke(gST->ConIn, &key);
        // 暫且設定僅兩種Kernel: Kernel1.bin及Kernel2.bin
        if(key.UnicodeChar == L'1' || key.UnicodeChar == L'2' )
        {
            Kernel(key.UnicodeChar);
            break;
        }
    }
}
  • Kernel()
static void Kernel(CHAR16 keyChar)
{
    EFI_HANDLE ImageHandle;
    EFI_STATUS Status = EFI_SUCCESS;
    EFI_FILE_PROTOCOL *bin;
    if (keyChar=='1')
    {
        Print(L"Enter 1 kernel...\n");
        Status = GetFileHandle(ImageHandle, L"\\Kernel1.bin",&bin);
    }
    if (keyChar=='2')
    {
        Print(L"Enter 2 kernel...\n");
        Status = GetFileHandle(ImageHandle, L"\\Kernel2.bin",&bin);
    }
    EFI_PHYSICAL_ADDRESS binAddr;
    Status = ReadFile(bin, &binAddr);
    asm("jmp %0"::"m"(binAddr)); // %0是第1個位址、%1是第2個位址,以此類推
}


總結

Day20至今本篇Day23完成ASM開發Kernel.bin與BootMenu.c以asm()連結之。距離完成開機畫面僅剩一哩路,謝謝一路相伴,我們明天見!


上一篇
【Day 22】自己寫UEFI Boot Menu (上)
下一篇
【Day 24】自己寫的UEFI開機畫面終於成形!
系列文
世界第一簡單的UEFI,實作打造自己的開機畫面31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言